package com.spider.spiderflowable.business.service.impl;

import com.spider.spiderflowable.business.service.TokenBlacklistService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import java.util.Date;
import javax.crypto.SecretKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.Cache.ValueWrapper;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;

/**
 * 使用chache内存缓存控制令牌是否失效来实现退出登录功能； 企业级系统可以使用Redis来代替。
 *
 * @author xiong.bo
 * @version 1.0
 * @date 2025/3/16 3:08 下午
 */

@Slf4j
@Service
public class TokenBlacklistServiceImpl implements TokenBlacklistService {

  private static final String SECRET_KEY = "gold";

  private static final String JTW_TOKEN_CACHE_KEY = "jwtTokenLogoutCache";

  @Autowired
  private CacheManager cacheManager;

//  private final CacheManager cacheManager;
//
//  // 通过构造函数注入
//  public TokenBlacklistServiceImpl(CacheManager cacheManager) {
//    this.cacheManager = cacheManager;
//  }

  /**
   * 将令牌加入黑名单 用户Token在黑名单中代表此token已失效
   *
   * @param token
   */
  @Override
  public void addToBlacklist(String token) {
    log.info("addToBlacklist token:{}", token);
    Cache cache = cacheManager.getCache(JTW_TOKEN_CACHE_KEY);
    if (cache != null) {
      // 写入到缓存
      cache.put(token, token);
      log.info("addToBlacklist成功,token:{}", token);
    }
  }

  /**
   * 检查令牌是否在黑名单中
   *
   * @param token
   * @return true: 失效，false：有效
   */
  @Override
  public boolean isBlacklisted(String token) {
    Cache cache = cacheManager.getCache(JTW_TOKEN_CACHE_KEY);
    if (cache != null) {
      ValueWrapper valueWrapper = cache.get(token);
      if (valueWrapper != null) {
        return true; // Token 失效
      }
    }
    return false;
  }

  // 从 JWT 中提取 jti
  private String getJtiFromToken(String token) {
    Claims claims = parseToken(token);
    return claims.getId(); // jti 是 JWT 的唯一标识
  }

  // 从 JWT 中获取过期时间
  public Long getExpirationTime(String token) {
    Claims claims = parseToken(token);
    Date expiration = claims.getExpiration();
    return expiration.getTime();
  }

  // 解析 JWT
  private Claims parseToken(String token) {
    SecretKey key = Keys.hmacShaKeyFor(SECRET_KEY.getBytes());
    return Jwts.parserBuilder()
        .setSigningKey(key)
        .build()
        .parseClaimsJws(token)
        .getBody();
  }

}
